﻿namespace WebCamera
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;

    public class FFPage : IBrowserPage
    {
        private WebCamera.BrowserWindow _BrowserWindow;
        private static string _ff_appdata;
        private static string _ff_program;
        private List<string> _files;
        private IntPtr _Handle;
        private int _Height;
        private Guid _ID;
        private List<Point> _points;
        private int _ScreenHeight;
        private int _ScreenWidth;
        private Socket _socket;
        private bool _socketConnected;
        private int _Width;
        private int _X;
        private int _Y;
        private bool allowSend;
        public const int STRING_LENGTH = 0x100;
        private const string UNKNOWN = "unknown";

        private FFPage()
        {
            this._socketConnected = false;
            this.allowSend = true;
        }

        public FFPage(IntPtr handle, WebCamera.BrowserWindow win)
        {
            this._socketConnected = false;
            this.allowSend = true;
            this._Handle = handle;
            this._BrowserWindow = win;
            this._ID = Guid.NewGuid();
            this._files = new List<string>();
            this._points = new List<Point>();
        }

        private void close()
        {
            this._socket.Close();
        }

        public void CombineImage(string file)
        {
            Bitmap bitmap = new Bitmap(this._Width - this.BrowserWindow.Edge, this._Height, PixelFormat.Format16bppRgb555);
            Graphics graphics = Graphics.FromImage(bitmap);
            for (int i = 0; i < this._files.Count; i++)
            {
                Image image = Image.FromFile(this._files[i]);
                graphics.DrawImage(image, this._points[i]);
                image.Dispose();
            }
            bitmap.Save(file);
        }

        private void connect()
        {
            this._socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            this._socket.Blocking = true;
            IPAddress address = Dns.GetHostEntry(Configration.FFHostIPAddress).AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(address, Configration.FFProxyPort);
            try
            {
                this._socket.Connect(remoteEP);
                this._socketConnected = this._socket.Connected;
                this._socket.SendBufferSize = 0;
            }
            catch (Exception exception)
            {
                WebCamera.Log.Write(exception);
                throw new FFHostException();
            }
        }

        public static List<IntPtr> GetPageHandlers(IntPtr window)
        {
            List<IntPtr> list = new List<IntPtr>();
            StringBuilder builder = new StringBuilder(0x100);
            if (IntPtr.Zero != window)
            {
                IntPtr hWnd = OSSupport.GetWindow(OSSupport.GetWindow(OSSupport.GetWindow(OSSupport.GetWindow(window, 5), 5), 5), 5);
                StringBuilder s = new StringBuilder(0x100);
                try
                {
                    OSSupport.GetClassName(hWnd.ToInt32(), s, 0x100);
                    if (s.ToString().Equals("MozillaContentWindowClass"))
                    {
                        hWnd = OSSupport.GetWindow(OSSupport.GetWindow(hWnd, 5), 5);
                        if (hWnd != IntPtr.Zero)
                        {
                            list.Add(hWnd);
                        }
                        hWnd = OSSupport.GetWindow(hWnd, 2);
                    }
                }
                catch (Exception exception)
                {
                    WebCamera.Log.Write(exception);
                }
            }
            return list;
        }

        public static void Init()
        {
            if (string.IsNullOrEmpty(_ff_appdata) || string.IsNullOrEmpty(_ff_program))
            {
                IDictionary environmentVariables = Environment.GetEnvironmentVariables();
                _ff_appdata = Path.Combine(environmentVariables["APPDATA"].ToString(), @"Mozilla\Firefox\Profiles");
                _ff_program = Path.Combine(environmentVariables["ProgramFiles"].ToString(), @"Mozilla Firefox\firefox.exe");
            }
            if (!Directory.Exists(_ff_appdata))
            {
                throw new FFHostException();
            }
            DirectoryInfo info = new DirectoryInfo(_ff_appdata);
            foreach (FileInfo info2 in info.GetFiles("compreg.dat", SearchOption.AllDirectories))
            {
                info2.Delete();
            }
            foreach (FileInfo info2 in info.GetFiles("xpti.dat", SearchOption.AllDirectories))
            {
                info2.Delete();
            }
            ProcessStartInfo startInfo = new ProcessStartInfo(_ff_program);
            startInfo.Arguments = "- console www.msn.com";
            Process process = Process.Start(startInfo);
        }

        public string PrintWindow()
        {
            string str;
            try
            {
                Bitmap image = new Bitmap(this._ScreenWidth - this.BrowserWindow.Edge, this._ScreenHeight, PixelFormat.Format16bppRgb555);
                Graphics graphics = Graphics.FromImage(image);
                IntPtr hdc = graphics.GetHdc();
                OSSupport.PrintWindow(this.Handle, hdc, 0);
                graphics.ReleaseHdc(hdc);
                graphics.Flush();
                str = string.Concat(new object[] { this._ID, "-", this._files.Count.ToString(), ".tmp" });
                str = Path.Combine(Configration.SavePath, str);
                image.Save(str);
                this._files.Add(str);
                this._points.Add(new Point(this.X, this.Y));
                //WebCamera.Log.Write("file::" + str + ";x:" + this._X.ToString() + ";y:" + this._Y.ToString());
            }
            catch (Exception exception)
            {
                WebCamera.Log.Write(exception);
                throw new FileCanNotSaveException();
            }
            return str;
        }

        private string recv()
        {
            string str = string.Empty;
            byte[] buffer = new byte[0x400];
            int num = 0;
            while (num++ < 90)
            {
                if (this._socket.Available > 0)
                {
                    int count = this._socket.Receive(buffer);
                    str = Encoding.ASCII.GetString(buffer, 0, count);
                    //WebCamera.Log.Write("<recv>" + str + "</recv>");
                    this.allowSend = true;
                    return str;
                }
                Thread.Sleep(100);
            }
            WebCamera.Log.Write("<recv>empty</recv>");
            this.allowSend = true;
            return str;
        }

        public void ScrollTo(int x, int y)
        {
            this._X = x;
            this._Y = y;
            this.send("x=" + x.ToString() + "&y=" + y.ToString());
        }

        private int send(string sendMsg)
        {
            return this.send(sendMsg, true);
        }

        private int send(string sendMsg, bool waitForResponse)
        {
            while (!this.allowSend)
            {
                Thread.Sleep(0x3e8);
            }
            this.connect();
            byte[] bytes = Encoding.ASCII.GetBytes("&" + sendMsg);
            int num = this._socket.Send(bytes);
            if (num > 0)
            {
                this.allowSend = !waitForResponse;
            }
            Console.Write("<" + sendMsg + "> is sent");
            return num;
        }

        private void test()
        {
        }

        public WebCamera.BrowserWindow BrowserWindow
        {
            get
            {
                return this._BrowserWindow;
            }
        }

        public IntPtr Handle
        {
            get
            {
                return this._Handle;
            }
        }

        public int Height
        {
            get
            {
                if (this._Height == 0)
                {
                    this.send("h=unknown");
                    int.TryParse(this.recv().Replace("h=", string.Empty), out this._Height);
                }
                return this._Height;
            }
        }

        public Guid ID
        {
            get
            {
                return this._ID;
            }
        }

        public bool IsDownloadCompleted
        {
            get
            {
                return true;
            }
        }

        public int ScreenHeight
        {
            get
            {
                if (this._ScreenHeight == 0)
                {
                    this.send("sh=unknown");
                    int.TryParse(this.recv().Replace("sh=", string.Empty), out this._ScreenHeight);
                }
                return this._ScreenHeight;
            }
        }

        public int ScreenWidth
        {
            get
            {
                if (this._ScreenWidth == 0)
                {
                    this.send("sw=unknown");
                    int.TryParse(this.recv().Replace("sw=", string.Empty), out this._ScreenWidth);
                }
                return this._ScreenWidth;
            }
        }

        public string Url
        {
            get
            {
                throw new Exception("The method or operation is not implemented.");
            }
        }

        public bool Visible
        {
            get
            {
                return true;
            }
            set
            {
            }
        }

        public int Width
        {
            get
            {
                if (this._Width == 0)
                {
                    this.send("w=unknown");
                    int.TryParse(this.recv().Replace("w=", string.Empty), out this._Width);
                }
                return this._Width;
            }
        }

        public int X
        {
            get
            {
                this.send("x=unknown");
                int.TryParse(this.recv().Replace("x=", string.Empty), out this._X);
                return this._X;
            }
            set
            {
                this._X = value;
                this.send("x=" + value.ToString(), false);
            }
        }

        public int Y
        {
            get
            {
                this.send("y=unknown");
                int.TryParse(this.recv().Replace("y=", string.Empty), out this._Y);
                return this._Y;
            }
            set
            {
                this._Y = value;
                this.send("y=" + value.ToString(), false);
            }
        }
    }
}

